package com.pay.ioopos.activity;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import com.pay.ioopos.BindState;
import com.pay.ioopos.DataFactory;
import com.pay.ioopos.ErrorListener;
import com.pay.ioopos.KeyCodeFactory;
import com.pay.ioopos.KeyInfo;
import com.pay.ioopos.KeyInfoListener;
import com.pay.ioopos.NetworkState;
import com.pay.ioopos.R;
import com.pay.ioopos.SubScreenFactory;
import com.pay.ioopos.fragment.TipVerticalFragment;
import com.pay.ioopos.service.NetworkService;
import com.pay.ioopos.sqlite.SettingHelper;

import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import static com.pay.ioopos.fragment.TipFragment.TipType.ERROR;

public abstract class AbstractActivity extends AppCompatActivity implements KeyInfoListener, ErrorListener {
    private static final String TAG = AbstractActivity.class.getSimpleName();
    private static boolean trustCertificates = false;
    private FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks;
    private Handler toastHandler = new Handler();
    private Toast toast;
    protected Fragment mainFragment;
    protected TextToSpeech speech;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NetworkService.start(this);
        registerFragmentLifecycleCallbacks();
        speech = new TextToSpeech(this, status ->  {});
        if (!trustCertificates) {
            trustCertificates();
            trustCertificates = true;
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getSupportFragmentManager().unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        Window window = getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_IMMERSIVE;//|View.SYSTEM_UI_FLAG_FULLSCREEN
        window.setAttributes(params);

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        KeyInfo keyInfo = KeyCodeFactory.getKeyInfo(keyCode);
        if (null == keyInfo) {
            return false;
        }
        if (keyInfo == KeyInfo.KEY_SEARCH) {
            SubScreenFactory.startSubScreenToWelcome(this);
            Intent intent = new Intent(this, StatisticsActivity.class);
            startActivity(intent);
            return false;
        } else if (keyInfo == KeyInfo.KEY_MENU) {
            SubScreenFactory.startSubScreenToWelcome(this);
            Intent intent = new Intent(this, SettingActivity.class);
            startActivity(intent);
            return false;
        }
        return onKeyDown(keyInfo);
    }

    @Override
    public void onError(String msg) {
        setMainFragment(new TipVerticalFragment(ERROR, msg));
    }

    public void speak(String text) {
        speech.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
    }

    public void showToast(String msg) {
        if (null != toast) {
            toast.cancel();
        }
        if (null == Looper.myLooper()) {
            Looper.prepare();
        }
        toastHandler.post(() -> {
            toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
            toast.show();
        });

    }

    protected void setMainFragment(Fragment fragment) {
        mainFragment = fragment;
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.activity_container, fragment);
        fragmentTransaction.commit();
    }

    @Deprecated
    protected void trustCertificates() {
        try {
            InputStream inStream = getAssets().open("app_campusplus_com.crt");
            CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");
            Certificate cer = cerFactory.generateCertificate(inStream);

            KeyStore kStore = KeyStore.getInstance("PKCS12");
            kStore.load(null, null);
            kStore.setCertificateEntry("trust", cer);

            KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyFactory.init(kStore, null);

            TrustManagerFactory tFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tFactory.init(kStore);

            SSLContext context = SSLContext.getInstance("TLS");
            context.init(keyFactory.getKeyManagers(), tFactory.getTrustManagers(), new SecureRandom());

            HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
        } catch (Exception e) {
            Log.e(TAG, "trustCertificates: ", e);
        }
    }

    private void registerFragmentLifecycleCallbacks() {
        fragmentLifecycleCallbacks = new FragmentManager.FragmentLifecycleCallbacks() {
            @Override
            public void onFragmentViewCreated(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull View v, @Nullable Bundle savedInstanceState) {
                if (f instanceof BindState) {
                    String transKey = DataFactory.getDataStore().getTransKey();
                    if (transKey.equals(SettingHelper.INIT_KEY)) {
                        ((BindState)f).onError(getString(R.string.please_bind_device_first));
                        speak(getString(R.string.please_bind_device_first));
                        return;
                    }
                }
                if (f instanceof NetworkState) {
                    ((NetworkState)f).run();
                }
            }

        };
        getSupportFragmentManager().registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true);
    }

}
